/**
 * \file
 *           tlmRmtCfgSrvApp.cpp
 * \brief
 *           Implements tlmRmtCfgSrvApp class for Telematics
 *           this is the derived class from tlmServiceApp clas.
 *           It's the service class for remote configuration 
 *
 * \par Author (last changes):
 *          - Zeng Jie
 *          - BUIC, Continental Automotive Holdings Co., Ltd.
 * \par Project Leader:
 *          -
 * \par Responsible Developer:
 *          - Zeng Jie
 *          - BUIC, Continental Automotive Holdings Co., Ltd.
 * \par Responsible Architect:
 *          - Zhang Fa
 *          - BUIC, Continental Automotive Holdings Co., Ltd.
 *
 * \par Project:
 *      DPCA2
 *
 * \par SW-Component:
 *      Telematics
 *
 * \par SW-Package:
 *      Telematics
 *
 * \par SW-Module:
 *      Telematics Application
 *
 * \par SW-Architecture Specification:
 *      DPCA - TELEMATICS SW DD
 *      05b
 *
 * \par SW-Design Specification:
 *      DPCA - TELEMATICS SW DD
 *      05b
 *
 * \par SW-Test Case Specification:
 *
 * \par CM-Info:
 *
 * \note
 *      This is a note.
 *
 * \bug
 *      - there are no known bugs
 *
 * \par Module-History:
 *
 * \verbatim
 * Date                Author					Reason
 * 10 Dec 2013        Zeng Jie              Initial Creation
 * The latest entry at the head of the history list.
 * \endverbatim
 *
 * \par Copyright Notice:
 * Copyright (C) 2012 Continental Automotive Holdings Co., Ltd.
 * Alle Rechte vorbehalten. All Rights Reserved.\n
 * The reproduction, transmission or use of this document or its contents is
 * not permitted without express written authority.\n
 * Offenders will be liable for damages. All rights, including rights created
 * by patent grant or registration of a utility model or design, are reserved.
 *
 */
#include "stdafx.h"
#include <wininet.h>
#include "tlmServiceFactory.h"
#include "tlmRmtCfgSrvApp.h"
#include "tlmRmtCfgDataInfo.h"
//## operation OnReceiveMsg(tlmServiceMsg)
#include "tlmServiceMsg.h"
#include "tlmRmtCfgSrvRpcSyncDesc.h"
#include "tlmRmtCfgSrvRpcAsyncDesc.h"
#include "teleLogTrace.h"
#include "ConnMgrApp.h"
#include "RmtCfgStateEvt.h"

#include "teleMainTimers.h"
#include "HiGraphTimer.h"

#include "HiGraphQueue.h"

extern HiGraphQueue gTeleQueue;
extern HiGraphTimer  gTeleTimer;

//## class tlmRmtCfgSrvApp
tlmRmtCfgSrvApp* tlmRmtCfgSrvApp::mpInstance;

/**
* \brief tlmRmtCfgSrvApp: this is constructor of tlmRmtCfgSrvApp class
*
* \note
*
* \param[in]
* - none
*
* \return
* - none
*/
tlmRmtCfgSrvApp::tlmRmtCfgSrvApp() : tlmServiceApp(), ActiveClass(), mAckStatus(TLM_ACK_STATUS_OK), mParaAdmin(),mParaNavi(),mParaWeb(){
}

/**
* \brief ~tlmRmtCfgSrvApp: this is destructor of tlmRmtCfgSrvApp class
*
* \note
*
* \param[in]
* - none
*
* \return
* - none
*/
tlmRmtCfgSrvApp::~tlmRmtCfgSrvApp() {
}

/**
* \brief GetAckStatus: get the ack status which indicates save parameters status
*
* \note
*
* \param[in]
* - none
*
* \return
* - uint8_t : ack status
*
* DesignID: MRN_TLM-SRV_SW_DD_113
*/
uint8_t tlmRmtCfgSrvApp::GetAckStatus() {
    return mAckStatus;
}

/**
* \brief GetInstance: retrieve or create new instace of tlmRmtCfgSrvApp
*
* \note
*
* \param[in]
* - none
*
* \return
* - tlmRmtCfgSrvApp*: pointer to tlmRmtCfgSrvApp instance
*
* DesignID: MRN_TLM-SRV_SW_DD_109
*/
tlmRmtCfgSrvApp* tlmRmtCfgSrvApp::GetInstance() {
    if(mpInstance == NIL)
    {
        mpInstance = new tlmRmtCfgSrvApp;
        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);
    }
    return mpInstance;
}

/**
* \brief destroyInstance: destroy action when the object is delete.
*
* \note
*
* \param[in]
* - none
*
* \return
* - none
*
*/
void tlmRmtCfgSrvApp::destroyInstance(void)
{
    //LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);
}

/**
* \brief initialize: this function initialization the service app.
*
* \note
*
* \param[in]
* - none
*
* \return
* - none
*
*/
void tlmRmtCfgSrvApp::initialize(void)
{
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);
    //TODO:add initialization actions at here
}

/**
 *
 * \brief  This function perform the syncronize call of process handler class.
 *
 * \param p [in] Pointer of the data structure of RPC call
 *
 * \return - none
 */
void tlmRmtCfgSrvApp::__SyncCall(RPC_IOCTL_PTR p) {
    //#[ operation __SyncCall(RPC_IOCTL_PTR)
    tlmRmtCfgSrvRpcSyncDesc desc(p);
    desc.send(p->ac->mExecutionThread);
    //#]
}

/**
 * \brief  This function perform the Asyncronize call of process handler class.
 *
 * TestID: 
 *
 * \param p [in]  Pointer of the data structure of RPC call
 *
 * \return - none
 */
void tlmRmtCfgSrvApp::__AsyncCall(RPC_IOCTL_PTR p) {
    //#[ operation __AsyncCall(RPC_IOCTL_PTR)
    tlmRmtCfgSrvRpcAsyncDesc* pDesc = new tlmRmtCfgSrvRpcAsyncDesc(p);
    pDesc->send(p->ac->mExecutionThread);
    //#]
}




/**
* \brief GetParaAdmin : get the admin parameter object
*
* \note
*
* \param[in]
* - none
*
* \return
* - tlmRmtCfgParaAdmin* : pointer to admin parameter object
*
* DesignID: MRN_TLM-SRV_SW_DD_108
*/
tlmRmtCfgParaAdmin* tlmRmtCfgSrvApp::GetParaAdmin() {
    tlmRmtCfgParaAdmin * pParaAdmin = NIL;

    pParaAdmin = &mParaAdmin;
    return pParaAdmin;
}
/**
* \brief GetParaNavi : get the Navi parameter object
*
* \note
*
* \param[in]
* - none
*
* \return
* - tlmRmtCfgParaNavi* : pointer to Navi parameter object
*
* DesignID: MRN_TLM-SRV_SW_DD_107
*/
tlmRmtCfgParaNavi* tlmRmtCfgSrvApp::GetParaNavi() {
    tlmRmtCfgParaNavi * pParaNavi = NIL;

    pParaNavi = &mParaNavi;
    
    return pParaNavi;
}
/**
* \brief GetParaWeb : get the Web parameter object
*
* \note
*
* \param[in]
* - none
*
* \return
* - tlmRmtCfgParaWeb* : pointer to Web parameter object
*
* DesignID: MRN_TLM-SRV_SW_DD_106
*/
tlmRmtCfgParaWeb* tlmRmtCfgSrvApp::GetParaWeb() {
    tlmRmtCfgParaWeb * pParaWeb= NIL;

    pParaWeb = &mParaWeb;
    
    return pParaWeb;
}

/**
* \brief SaveParameters: Save parameters of remote configuration service
*
* \note
*
* \param[in]
* - none
*
* \return
* - uint8_t: save status
*
* DesignID: MRN_TLM-SRV_SW_DD_112
*/
uint8_t tlmRmtCfgSrvApp::SaveParameters() {
    uint8_t status=TLM_ACK_STATUS_OK;
    status = mParaWeb.Save(); 
    if(status == TLM_ACK_STATUS_OK)
    {  
    	status = mParaNavi.Save(); 
    }  
    
    if(status == TLM_ACK_STATUS_OK)
    {  
    	status = mParaAdmin.Save(); 
    } 
    
    return status;
    //#]
}
/**
* \brief SendMsg: send the messag to server 
*
* \note
*
* \param[in]
* - msg: pointer to message object that include the message which shall be send.
*
* \return
* - none
*
* DesignID: MRN_TLM-SRV_SW_DD_111
*/
void tlmRmtCfgSrvApp::SendMsg(tlmServiceMsg* msg) { /*DG CPP2ISQP-ISQPcpp Rule 8.7.1-SCC_GRANT_0006*/
    //#]
    
    SendHttpMsg(msg->GetOutMsgPtr(),msg->GetTotalSize());

}
void tlmRmtCfgSrvApp::tlmRmtCfgSrvApp_makeAsyncCall(DWORD funcId,DWORD* pData,DWORD size)
{
	LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELE]:tlmRmtCfgSrvApp::makeAsyncCall %d\n", funcId);
	s_RPC_IOCTL mIoCTL;

	/* RPC IOCTL stucture */
    mIoCTL.ac = this;
	mIoCTL.dmFuncID = static_cast<uc8_t>(funcId);
	mIoCTL.lpInBuffer = reinterpret_cast<LPVOID>(pData);
	mIoCTL.nInBufferSize = static_cast<uc8_t>(size);
	mIoCTL.lpOutBuffer = 0;
	mIoCTL.nOutBufferSize = 0;

	this->AsyncCall(&mIoCTL);
}
/**
* \brief OnReceiveMsg: this function is called when received message
* 
* \note
*
* \param[in]
* - srvMsg: pointere to serviceMsg object which is the received message
*
* \return
* - none
*
* DesignID: MRN_TLM-SRV_SW_DD_110
*/
void tlmRmtCfgSrvApp::OnReceiveMsg(tlmServiceMsg* srvMsg) {
    //#[ operation OnReceiveMsg(tlmServiceMsg)
    s_RPC_IOCTL lRpc;


	/* RPC IOCTL stucture */
	lRpc.ac = this;
	lRpc.dmFuncID = FUNCID_TLM_RMT_CFG_HANDLE_MSG;
	lRpc.lpInBuffer = reinterpret_cast<LPVOID *>(&srvMsg);
	lRpc.lpOutBuffer =  NIL;
	lRpc.nInBufferSize = static_cast<uc8_t>(sizeof(srvMsg));
	lRpc.nOutBufferSize = 0;


	this->AsyncCall(&lRpc);

    
    //__OnReceiveMsg(srvMsg);
    //#]
}

/**
* \brief __OnReceiveMsg:This function is the actual handler function to process the message 
*               it shall save the message if it's incoming traffic message
*               parse the data infomation section, and process it. 
* 
* \note
*
* \param[in]
* - none
*
* \return
* - none
*
* DesignID: MRN_TLM-SRV_SW_DD_102
*/
void tlmRmtCfgSrvApp::__OnReceiveMsg(tlmServiceMsg* srvMsg) {
	uint8_t msgType=0;
	bool_t retVal=true;

    if(srvMsg==NIL)
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
        retVal = false;
    }
    else
    {
        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg:0x%x\n", __FUNCTION__,srvMsg);
    
        //#[ operation __OnReceiveMsg(tlmServiceMsg)
        //srvMsg->SaveMsg();

        //here can process the message
        retVal = srvMsg->HandleData(); 
        if(retVal)
        {
            srvMsg->GetMsgType(msgType);
            switch(msgType)
            {
                case TLM_MSG_TYPE_RMT_CFG_PENDING:
                    {
                    //__OnReceivePendingMsg(srvMsg);
                        gTeleQueue.postEvent(EVT_RMTCFG_RcvPendingMsg, reinterpret_cast<uint32_t>(srvMsg));
                        gTeleTimer.SetTimer(RmtCfgSetCfgTimer, TLM_RMT_CFG_TIMEOUT, EVT_RMTCFG_SetCfgTimeOut, NIL);
                        
                        break;    
                    }

                case TLM_MSG_TYPE_RMT_CFG_REQUEST:
                    {
                    //__OnReceiveReqParaMsg(srvMsg);
                        gTeleQueue.postEvent(EVT_RMTCFG_RcvGetCfgMsg, reinterpret_cast<uint32_t>(srvMsg));
                        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>start get cfg timer\n", __FUNCTION__);
                        gTeleTimer.SetTimer(RmtCfgGetCfgTimer, TLM_RMT_CFG_TIMEOUT, EVT_RMTCFG_GetCfgTimeOut, NIL);
                        break; 
                    }
                default:
                    {
                        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, invalid msg type[%d]\n", __FUNCTION__,msgType);
                        break;
                    }
            }
        }
        else
        {
            LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, Handle data failed\n", __FUNCTION__);
        }

    }


    return;

    
    
    //#]
}


void tlmRmtCfgSrvApp::CheckNewPendMsg(tlmServiceMsg* srvMsg) {
    //This function shall be called when receive pending message while the previous set config procss has not completed.
    uint16_t newMsgId = 0;
    uint16_t curMsgId = 0;
    bool_t retVal = false;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(srvMsg == NIL)
    {
        retVal = false;
        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<%s>, srvMsg is NIL\n", __FUNCTION__);
    }

    if(retVal)
    {
        newMsgId = srvMsg->GetMsgUniqueId();
        if(mCurPendingMsg != NIL)
        {
            curMsgId = mCurPendingMsg->GetMsgUniqueId();
        }

        if(newMsgId != curMsgId)
        {//received message is different with the current one 
            gTeleQueue.postEvent(EVT_RMTCFG_RcvNewPendingMsg, reinterpret_cast<uint32_t>(srvMsg));
        }
        else
        {//TODO: this branch is used to test, it should be delete.
            gTeleQueue.postEvent(EVT_RMTCFG_RcvNewPendingMsg, reinterpret_cast<uint32_t>(srvMsg));
        }
    }

    
}

void tlmRmtCfgSrvApp::onReceiveNewPendMsg(tlmServiceMsg* srvMsg) {
   

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(mCurPendingMsg != NIL)
    {
        delete mCurPendingMsg;
        mCurPendingMsg = NIL;
    }
}

void tlmRmtCfgSrvApp::CheckNewGetCfgMsg(tlmServiceMsg* srvMsg) {
    //This function shall be called when receive pending message while the previous set config procss has not completed.
    uint16_t newMsgId = 0;
    uint16_t curMsgId = 0;
    bool_t retVal = true;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(srvMsg == NIL)
    {
        retVal = false;
        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<%s>, srvMsg is NIL\n", __FUNCTION__);
    }

    if(retVal)
    {
        newMsgId = srvMsg->GetMsgUniqueId();

        if(mCurGetCfgMsg != NIL)
        {
            curMsgId = mCurGetCfgMsg->GetMsgUniqueId();
        }
        

        if(newMsgId != curMsgId)
        {//received message is different with the current one 
            gTeleQueue.postEvent(EVT_RMTCFG_RcvNewGetCfgMsg, reinterpret_cast<uint32_t>(srvMsg));
        }
        else
        {//TODO: this branch is used to test, it should be delete.
            gTeleQueue.postEvent(EVT_RMTCFG_RcvNewGetCfgMsg, reinterpret_cast<uint32_t>(srvMsg));
        }
    }
    
    
}

void tlmRmtCfgSrvApp::onReceiveNewGetCfgMsg(tlmServiceMsg* srvMsg) {
    
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(mCurGetCfgMsg != NIL)
    {
        delete mCurGetCfgMsg;
        mCurGetCfgMsg = NIL;
    }
}



void tlmRmtCfgSrvApp::OnReqConnection(void) {

//    E_CONN_STATUS status;
/*
    ConnMgrApp* pConnMgrApp = const_cast<ConnMgrApp*>(&(ConnMgrApp::getInstance()));
    if(pConnMgrApp)
    {
        //TODO: the mSetSessionId is not enough, there should be getsessionID, need to think about it.
        if(mSetSessionId == 0)
        {//has not request network, need to set up it.
            pConnMgrApp->onReqConnection(tlmSrcTlm,&mSetSessionId,&status);
        }
        else
        {//the request has been done, no need to set up it again
            status = pConnMgrApp->getConnectionState();
        }

        if(status != CS_CONNECTED)
        {
            gTeleQueue.postEvent(EVT_RMTCFG_WaitConnAvailable, NIL);
        }
        else
        {
            gTeleQueue.postEvent(EVT_RMTCFG_ConnAvailable, NIL);
        }

        
    }
    else
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, ConnMgrApp instance is NIL\n", __FUNCTION__);
    }
*/
    //TODO: delete it, this is just to do verification.
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);
    gTeleQueue.postEvent(EVT_RMTCFG_ConnAvailable, NIL);
    //gTeleQueue.postEvent(EVT_RMTCFG_WaitConnAvailable, NIL);
    


}
void tlmRmtCfgSrvApp::RequestConnection(void) {
     E_CONN_STATUS status;
    ConnMgrApp* pConnMgrApp = const_cast<ConnMgrApp*>(&(ConnMgrApp::getInstance()));
    if(pConnMgrApp)
    {
        //TODO: the mSetSessionId is not enough, there should be getsessionID, need to think about it.
        if(mSetSessionId == 0)
        {//has not request network, need to set up it.
            pConnMgrApp->onReqConnection(tlmSrcTlm,&mSetSessionId,&status);
        }
        else
        {//the request has been done, no need to set up it again
            status = pConnMgrApp->getConnectionState();
        }

        if(status == CS_CONNECTED)
        {
            gTeleQueue.postEvent(EVT_RMTCFG_ConnAvailable, NIL);
        }
        else
        {
        //TODO:for test add this branch, should delete it after test
            gTeleQueue.postEvent(EVT_RMTCFG_ConnAvailable, NIL);
        }

        
    }
    else
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, ConnMgrApp instance is NIL\n", __FUNCTION__);
    }
}


/**
* \brief __OnReceiveReqParaMsg: this function is used to process reqPara(28) message
*               it get current configuration if it's requested, then create sendPara(31)
*               message and send it to server
*
* \note
*
* \param[in]
* - srvMsg: pointer to message which should be reqPara message
*
* \return
* - none
*
* DesignID: MRN_TLM-SRV_SW_DD_104
*/
void tlmRmtCfgSrvApp::__OnReceiveReqParaMsg(tlmServiceMsg* srvMsg) {
    //#[ operation __OnReceiveReqParaMsg(tlmServiceMsg)
    //Received an pending message(mstType:0x28), need send parameters message to offboard server.
    tlmRmtCfgParaWeb *pParaWeb = NIL;     
    tlmRmtCfgParaNavi *pParaNavi = NIL;
    tlmRmtCfgParaAdmin *pParaAdmin = NIL; 
    tlmRmtCfgDataInfo *pDataInfo = NIL;

    if(NIL == srvMsg)
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
    }
    else
    {
        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, receive reqPara message\n", __FUNCTION__);
        pDataInfo = reinterpret_cast<tlmRmtCfgDataInfo*>(srvMsg->GetDataInfo());

        if(pDataInfo != NIL)
        {
            //check if the parameters is requested to send
            pParaWeb = pDataInfo->GetParaWeb();
            if(pParaWeb!=NIL)
            {
                mParaWeb.SetRequested(pParaWeb->IsRequested());  
                pParaWeb->ClearRequested();
            } 

            //check if the parameters is requested to send
            pParaNavi = pDataInfo->GetParaNavi();
            if(pParaNavi!=NIL)
            {
                mParaNavi.SetRequested(pParaNavi->IsRequested());
                pParaNavi->ClearRequested();
            } 

            //check if the parameters is requested to send
            pParaAdmin = pDataInfo->GetParaAdmin();
            if(pParaAdmin!=NIL)
            {   
                //set the current para flag
                mParaAdmin.SetRequested(pParaAdmin->IsRequested()); 

                //clear the component in message.
                pParaAdmin->ClearRequested();
            } 
        }



        //SetupHttpConnection();  

        tlmServiceMsg* pSendParaMsg=NIL;
        pSendParaMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(TLM_SRV_TYPE_REMOTE_CONFIG,TLM_MSG_TYPE_RMT_CFG_SEND_PARA);

        if(pSendParaMsg!=NIL)
        {    
            pSendParaMsg->SetItsService(this);
            pSendParaMsg->Init();
            pSendParaMsg->Fill();
            SendMsg(pSendParaMsg);

            //TODO: shall delete sendPara message after send successfully.
        }         
        else
        {
            LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, create sendPara message failed\n", __FUNCTION__);
        }

        //After send the message, shall clear the requested flag.
        mParaWeb.ClearRequested();
        mParaNavi.ClearRequested();
        mParaAdmin.ClearRequested();

    }

    //#]
}

/**
* \brief __OnReceiveSetParaMsg: this function is used to process setPara(30) message
*           it update current configuration, and save it into NVM
*
* \note
*
* \param[in]
* - srvMsg: pointer to message which should be setPara message
*
* \return
* - none
*
* DesignID: MRN_TLM-SRV_SW_DD_105
*/
void tlmRmtCfgSrvApp::__OnReceiveSetParaMsg(tlmServiceMsg* srvMsg) {
    //#[ operation __OnReceiveSetParaMsg(tlmServiceMsg)
    //Received an set para message(mstType:0x30), need update the configuration parameters.  
    
    //the parameters has been parsed in srvMsg, we just need to update it. 
    
    tlmRmtCfgParaWeb *pParaWeb = NIL;     
    tlmRmtCfgParaNavi *pParaNavi = NIL;
    tlmRmtCfgParaAdmin *pParaAdmin = NIL;
    tlmRmtCfgDataInfo * pDataInfo = NIL;

    if(NIL == srvMsg)
    {
	    //LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
    }
    else
    {
        
        pDataInfo = reinterpret_cast<tlmRmtCfgDataInfo*>(srvMsg->GetDataInfo());
        if(pDataInfo != NIL)
        {
            //update the web parameters
            pParaWeb = pDataInfo->GetParaWeb();
            if(pParaWeb!=NIL)
            {
                mParaWeb.Update(pParaWeb);
            } 

            //update the navi parameters  
            pParaNavi = pDataInfo->GetParaNavi();
            if(pParaNavi!=NIL)
            {
                mParaNavi.Update(pParaNavi);
            }  

            //update the Admin parameters
            pParaAdmin = pDataInfo->GetParaAdmin();
            if(pParaAdmin!=NIL)
            {
                mParaAdmin.Update(pParaAdmin);
            }
            mAckStatus=SaveParameters();  
        }
        else
        {
            mAckStatus=TLM_ACK_STATUS_KO;  
        }

        //After update message, we shall send Ack message to offboard server.  

        //SetupHttpConnection();  

        tlmServiceMsg* pAckMsg=NIL;
        pAckMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(TLM_SRV_TYPE_REMOTE_CONFIG,TLM_MSG_TYPE_RMT_CFG_ACK);

        if(pAckMsg!=NIL)
        {    
            pAckMsg->SetItsService(this);
            pAckMsg->Init();
            pAckMsg->Fill();
            SendMsg(pAckMsg);
        }

    }
    //#]
}


void tlmRmtCfgSrvApp::SendHttpMsg(uint8_t* msgPayload, uint32_t length) {

    bool_t retVal=true; 
    HINTERNET hRequest = NULL;
    HINTERNET hConnect=NULL;    
    HINTERNET hSession = NULL;
    uint32_t contentLen = 0;
    uint32_t httpStatus=0;

    if(!hSession)
    {
        hSession = InternetOpen( TEXT("RemoteConfigMsg"), INTERNET_OPEN_TYPE_PRECONFIG,
                                                        NULL, NULL, 0);
        if(!hSession)
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to open session>\r\n",__FUNCTION__);
            retVal=false;    
        }
    }
    

    if(retVal && !hConnect)
    {
         hConnect = InternetConnect(hSession, TEXT("192.168.1.25"), INTERNET_DEFAULT_HTTP_PORT,
                                                                NULL, NULL, INTERNET_SERVICE_HTTP,NULL, NULL);
        if (!hConnect)
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to connect>\r\n",__FUNCTION__);
            retVal=false; 
        }
        
    }

    if(retVal && !hRequest)
    {
        hRequest = HttpOpenRequest(hConnect, TEXT("POST"), TEXT("RemoteCfg"), 
                            NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
        if (!hRequest)
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to open request handle>\r\n",__FUNCTION__);
            retVal=false;
        }
        else
        {            
            if(!HttpSendRequest(hRequest, NULL, -1, msgPayload, length))
            {                            
                DWORD dw = GetLastError();
                LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to send request,  err[%d]>\r\n",__FUNCTION__, dw);
                retVal=false;
            }
        }

    }
    if(retVal)
    {
        DWORD dwSize = 128;
        char * lpOutBuffer = new char[dwSize];

        //StringCchPrintfA((LPSTR)lpOutBuffer,dwSize,"Content-Length");


        if(!HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_CODE  , (LPVOID)lpOutBuffer,&dwSize,NULL))
        {
            DWORD dw = GetLastError();
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed query status,  err[%d][%d]>\r\n",__FUNCTION__, dw,dwSize);
            retVal = false;
        }
        else
        {
            //int len = atol(static_cast<const char *>(lpOutBuffer));
            #ifdef UNICODE
            httpStatus = _wtol(reinterpret_cast<const wchar_t *>(lpOutBuffer));
            #else
            httpStatus = atol(lpOutBuffer);
            #endif

            if(httpStatus != HTTP_STATUS_OK )
            {
                retVal = false;
                LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::status[%d]>\r\n",__FUNCTION__, httpStatus);
            }           
            

        }

        
    }

    if(retVal)
    {
        DWORD dwSize = 10;
        char * lpOutBuffer = new char[dwSize];

        //StringCchPrintfA((LPSTR)lpOutBuffer,dwSize,"Content-Length");


        if(!HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH , (LPVOID)lpOutBuffer,&dwSize,NULL))
        {
            DWORD dw = GetLastError();
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed queryinfo,  err[%d][%d]>\r\n",__FUNCTION__, dw,dwSize);
            retVal = false;
        }
        else
        {
            //int len = atol(static_cast<const char *>(lpOutBuffer));
            #ifdef UNICODE
            contentLen = _wtol(reinterpret_cast<const wchar_t *>(lpOutBuffer));
            #else
            contentLen = atol(lpOutBuffer);
            #endif
            
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::size[%d]>\r\n",__FUNCTION__, contentLen);

            if(contentLen == 0)
            {//This indicates its an HTTP OK response
                LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::httprsp:OK>\r\n",__FUNCTION__);
                gTeleQueue.postEvent(EVT_RMTCFG_RcvHttpOKResp, NIL);
            }
        }

        
    }
   

    if(retVal && (contentLen != 0))
    {
        DWORD  dwBytesRead=0;
        DWORD  dwSize=0;
        uint8_t * pcBuffer=NIL;

        uint8_t *msgPayload = new uint8_t[contentLen];

        if(msgPayload != NIL)
        {
            uint8_t * pTemp = msgPayload;
            
            do
            {	
                dwBytesRead=0;
                if (!InternetQueryDataAvailable(hRequest,&dwSize,0,0))
                {
                    LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to query data>\r\n",__FUNCTION__);
                    retVal=false;
                    break;
                }

                LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::dwSize[%d]>\r\n",__FUNCTION__, dwSize);

                pcBuffer = new uint8_t[dwSize];
                
                
                if(InternetReadFile(hRequest, (LPVOID)pcBuffer, dwSize, &dwBytesRead))
                {
                    LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::read data bytes[%d]>\r\n",__FUNCTION__, dwBytesRead);   	

                    memcpy(pTemp, pcBuffer, dwBytesRead);

                    pTemp += dwBytesRead;
                }
                else
                {
                    LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s::Failed to read file>\r\n",__FUNCTION__);
                    
                    retVal = false;
                    
                }

                delete [] pcBuffer;            
            }while((dwBytesRead>0) && (retVal!=false));

            OnReceiveHttpMsg(msgPayload, contentLen);

            delete [] msgPayload;
        }

        


        
    }


    if(hRequest)
    {
        if(InternetCloseHandle(hRequest))
        {
            hRequest=NIL;
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>close hRequest\r\n",__FUNCTION__);
        }
        else
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>Failed close hRequest, [%d]\r\n",__FUNCTION__, GetLastError());
        }
    }

    if(hConnect)
    {
        if(InternetCloseHandle(hConnect))
        {
            hConnect=NIL;
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>close hConnect\r\n",__FUNCTION__);
        }
        else
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>Failed close hConnect, [%d]\r\n",__FUNCTION__, GetLastError());
        }
    }
    if(hSession)
    {
        if(InternetCloseHandle(hSession))
        {
            hSession=NIL;
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>close hSession\r\n",__FUNCTION__);
        }
        else
        {
            LOG_PRINT(DPCA_TELE_MAIN_INFO, "[TLM_MSGSRV]:<%s>Failed close hSession, [%d]\r\n",__FUNCTION__, GetLastError());
        }
    }
    
}

void tlmRmtCfgSrvApp::OnReceiveHttpMsg(uint8_t* msgPayload, uint32_t length){
    bool_t retVal=true;
    tlmServiceMsg * srvMsg=NIL;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);
    
    if( msgPayload == NIL || length == 0 ){  
    	LOG_PRINT( DPCA_TELE_MAIN_ERROR, "[TLM_RMTCFG] invalid payload or length %s", __FUNCTION__);
        retVal = false;
    }
    if(retVal)
    {

    //create a new srvMsg instance, it shall pass to the service, and delete by the service
        srvMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(msgPayload, length);
        if(srvMsg != NIL)
        {
        
            //TODO: if sendHttpMsg run in separate thread, need use RPC call.
        
            __OnReceiveHttpMsg(srvMsg);
        }
    }
}

void tlmRmtCfgSrvApp::__OnReceiveHttpMsg(tlmServiceMsg* srvMsg) {
    uint8_t srvType=0;
    uint8_t msgType=0;
    bool_t retVal=true;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);

    if(srvMsg==NIL)
    {
        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_RMTCFG]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
        retVal = false;
    }

    if(retVal)
    {
        retVal = srvMsg->ParseInit();
    }
    

    if(retVal)
    {
        srvMsg->GetSrvType(srvType);        

        if(srvType != TLM_SRV_TYPE_REMOTE_CONFIG)
        {
            retVal = false;
            LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s> invalid srvType[%d]\n", __FUNCTION__,srvType);
        }      
            
    }

    if(retVal)
    {
        //can only receive set para messag via HTTP.
        srvMsg->GetMsgType(msgType);
        if(msgType != TLM_MSG_TYPE_RMT_CFG_SET_PARA) 
        {
            retVal = false;
            LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s> invalid msgType[%d]\n", __FUNCTION__,msgType);
        }
    }

    if(retVal)
    {
        //here can process the message
        retVal = srvMsg->HandleData();  
    }

    if(retVal)
    {
        //as only set para message shall be received via HTTP
        //This function shall only process set para message, so just send this event.
        //The last http 200 ok response message is not processed at here.
        gTeleQueue.postEvent(EVT_RMTCFG_RcvSetCfgMsg, reinterpret_cast<uint32_t>(srvMsg));
    }


    return;

    
    
    //#]
}



void tlmRmtCfgSrvApp::HandleGetCfgMsg(tlmServiceMsg* srvMsg) {

//#[ operation __OnReceiveReqParaMsg(tlmServiceMsg)
    //Received an pending message(mstType:0x28), need send parameters message to offboard server.
    tlmRmtCfgParaWeb *pParaWeb = NIL;     
    tlmRmtCfgParaNavi *pParaNavi = NIL;
    tlmRmtCfgParaAdmin *pParaAdmin = NIL; 
    tlmRmtCfgDataInfo *pDataInfo = NIL;

    if(NIL == srvMsg)
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
    }
    else
    {

        uint8_t msgType=0;

        if(mCurGetCfgMsg != NIL)
        {//delete current message, which should be previous session.
            delete mCurGetCfgMsg;
            mCurGetCfgMsg = NIL;
        }
        mCurGetCfgMsg = srvMsg;
            
        srvMsg->GetMsgType(msgType);
        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, receive reqPara message[%d]\n", __FUNCTION__,msgType);
        pDataInfo = reinterpret_cast<tlmRmtCfgDataInfo*>(srvMsg->GetDataInfo());

        if(pDataInfo != NIL)
        {
            //check if the parameters is requested to send
            pParaWeb = pDataInfo->GetParaWeb();
            if(pParaWeb!=NIL)
            {
                mParaWeb.SetRequested(pParaWeb->IsRequested());  
                pParaWeb->ClearRequested();
            } 

            //check if the parameters is requested to send
            pParaNavi = pDataInfo->GetParaNavi();
            if(pParaNavi!=NIL)
            {
                
                mParaNavi.SetRequested(pParaNavi->IsRequested());      
                
            } 

            //check if the parameters is requested to send
            pParaAdmin = pDataInfo->GetParaAdmin();
            if(pParaAdmin!=NIL)
            {   
                //set the current para flag
                mParaAdmin.SetRequested(pParaAdmin->IsRequested()); 

                //clear the component in message.
                pParaAdmin->ClearRequested();
            } 
        }

        //gTeleQueue.postEvent(EVT_RMTCFG_ReqConnection, NIL);
        RequestConnection();

        

    }



    
}

void tlmRmtCfgSrvApp::HandlePendingMsg(tlmServiceMsg* srvMsg) {

    if(srvMsg != NIL)
    {
        if(mCurPendingMsg != NIL)
        {//delete current message, which should be previous session.
            delete mCurPendingMsg;
            mCurPendingMsg = NIL;
        }
        
        mCurPendingMsg = srvMsg;
        //gTeleQueue.postEvent(EVT_RMTCFG_ReqConnection, NIL);    
        LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);
        RequestConnection();
    }
    else
    {
        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<%s>, srvMsg is NIL\n", __FUNCTION__);
    }
    
}

void tlmRmtCfgSrvApp::HandleSetConfigMsg(tlmServiceMsg* srvMsg) {

    tlmRmtCfgParaWeb *pParaWeb = NIL;     
    tlmRmtCfgParaNavi *pParaNavi = NIL;
    tlmRmtCfgParaAdmin *pParaAdmin = NIL;
    tlmRmtCfgDataInfo * pDataInfo = NIL;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>\n", __FUNCTION__);

    if(NIL == srvMsg)
    {
	    LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<tlmRmtCfgSrvApp::%s>, srvMsg is NIL\n", __FUNCTION__);
    }
    else
    {
        
        pDataInfo = reinterpret_cast<tlmRmtCfgDataInfo*>(srvMsg->GetDataInfo());
        if(pDataInfo != NIL)
        {
            //update the web parameters
            pParaWeb = pDataInfo->GetParaWeb();
            if(pParaWeb!=NIL)
            {
                mParaWeb.Update(pParaWeb);
            } 

            //update the navi parameters  
            pParaNavi = pDataInfo->GetParaNavi();
            if(pParaNavi!=NIL)
            {
                mParaNavi.Update(pParaNavi);
            }  

            //update the Admin parameters
            pParaAdmin = pDataInfo->GetParaAdmin();
            if(pParaAdmin!=NIL)
            {
                mParaAdmin.Update(pParaAdmin);
            }
            mAckStatus=SaveParameters();  
        }
        else
        {
            mAckStatus=TLM_ACK_STATUS_KO;  
        }
        

        //After update message, we shall send Ack message to offboard server.  

        //gTeleQueue.postEvent(EVT_RMTCFG_ReqConnection, NIL);
        RequestConnection();
        

        

    }
}

void tlmRmtCfgSrvApp::SendParaMsg(void){
 
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    tlmServiceMsg* pSendParaMsg=NIL;
    pSendParaMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(TLM_SRV_TYPE_REMOTE_CONFIG,TLM_MSG_TYPE_RMT_CFG_SEND_PARA);

    if(pSendParaMsg!=NIL)
    {    
        pSendParaMsg->SetItsService(reinterpret_cast<tlmServiceApp*>(GetInstance()));
        pSendParaMsg->Init();
        pSendParaMsg->Fill();
        SendMsg(pSendParaMsg);

        delete pSendParaMsg;

    }         
    else
    {
        LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TLM_MSGSRV]:<%s>, create sendPara message failed\n", __FUNCTION__);
    }

    //After send the message, shall clear the requested flag.
    mParaWeb.ClearRequested();
    mParaNavi.ClearRequested();
    mParaAdmin.ClearRequested();

}

void tlmRmtCfgSrvApp::SendConMsg(void){

    tlmServiceMsg* pConMsg=NIL;

    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);
    
    pConMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(TLM_SRV_TYPE_REMOTE_CONFIG,TLM_MSG_TYPE_RMT_CFG_CONNECT);
    
    if(pConMsg!=NIL)
    {
        pConMsg->Init();
        pConMsg->Fill();

        SendMsg(pConMsg);

        delete pConMsg;

    }
}

void tlmRmtCfgSrvApp::SendAckMsg(void){
   
    tlmServiceMsg* pAckMsg=NIL;
    pAckMsg = tlmServiceFactory::GetInstance()->CreateSrvMsg(TLM_SRV_TYPE_REMOTE_CONFIG,TLM_MSG_TYPE_RMT_CFG_ACK);

    if(pAckMsg!=NIL)
    {    
        pAckMsg->SetItsService(reinterpret_cast<tlmServiceApp*>(GetInstance()));
        pAckMsg->Init();
        pAckMsg->Fill();
        SendMsg(pAckMsg);

        delete pAckMsg;
    }
}

void tlmRmtCfgSrvApp::OnGetCfgTimeOut(void){
 
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(mCurGetCfgMsg != NIL)
    {
        delete mCurGetCfgMsg;
        mCurGetCfgMsg = NIL;
    }

}

void tlmRmtCfgSrvApp::OnSetCfgTimeOut(void){
 
    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TLM_MSGSRV]:<%s>\n", __FUNCTION__);

    if(mCurPendingMsg != NIL)
    {
        delete mCurPendingMsg;
        mCurPendingMsg = NIL;
    }

}


